home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / Delphi 3.0 / DATA.Z / spin.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-01-30  |  16.7 KB  |  631 lines

  1. unit Spin;
  2.  
  3. interface
  4.  
  5. uses Windows, Classes, StdCtrls, ExtCtrls, Controls, Messages, SysUtils,
  6.   Forms, Graphics, Menus, Buttons;
  7.  
  8. const
  9.   InitRepeatPause = 400;  { pause before repeat timer (ms) }
  10.   RepeatPause     = 100;  { pause before hint window displays (ms)}
  11.  
  12. type
  13.  
  14.   TTimerSpeedButton = class;
  15.  
  16. { TSpinButton }
  17.  
  18.   TSpinButton = class (TWinControl)
  19.   private
  20.     FUpButton: TTimerSpeedButton;
  21.     FDownButton: TTimerSpeedButton;
  22.     FFocusedButton: TTimerSpeedButton;
  23.     FFocusControl: TWinControl;
  24.     FOnUpClick: TNotifyEvent;
  25.     FOnDownClick: TNotifyEvent;
  26.     function CreateButton: TTimerSpeedButton;
  27.     function GetUpGlyph: TBitmap;
  28.     function GetDownGlyph: TBitmap;
  29.     procedure SetUpGlyph(Value: TBitmap);
  30.     procedure SetDownGlyph(Value: TBitmap);
  31.     function GetUpNumGlyphs: TNumGlyphs;
  32.     function GetDownNumGlyphs: TNumGlyphs;
  33.     procedure SetUpNumGlyphs(Value: TNumGlyphs);
  34.     procedure SetDownNumGlyphs(Value: TNumGlyphs);
  35.     procedure BtnClick(Sender: TObject);
  36.     procedure BtnMouseDown (Sender: TObject; Button: TMouseButton;
  37.       Shift: TShiftState; X, Y: Integer);
  38.     procedure SetFocusBtn (Btn: TTimerSpeedButton);
  39.     procedure AdjustSize (var W: Integer; var H: Integer);
  40.     procedure WMSize(var Message: TWMSize);  message WM_SIZE;
  41.     procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
  42.     procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  43.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  44.   protected
  45.     procedure Loaded; override;
  46.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  47.     procedure Notification(AComponent: TComponent;
  48.       Operation: TOperation); override;
  49.   public
  50.     constructor Create(AOwner: TComponent); override;
  51.     procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  52.   published
  53.     property Align;
  54.     property Ctl3D;
  55.     property DownGlyph: TBitmap read GetDownGlyph write SetDownGlyph;
  56.     property DownNumGlyphs: TNumGlyphs read GetDownNumGlyphs write SetDownNumGlyphs default 1;
  57.     property DragCursor;
  58.     property DragMode;
  59.     property Enabled;
  60.     property FocusControl: TWinControl read FFocusControl write FFocusControl;
  61.     property ParentCtl3D;
  62.     property ParentShowHint;
  63.     property PopupMenu;
  64.     property ShowHint;
  65.     property TabOrder;
  66.     property TabStop;
  67.     property UpGlyph: TBitmap read GetUpGlyph write SetUpGlyph;
  68.     property UpNumGlyphs: TNumGlyphs read GetUpNumGlyphs write SetUpNumGlyphs default 1;
  69.     property Visible;
  70.     property OnDownClick: TNotifyEvent read FOnDownClick write FOnDownClick;
  71.     property OnDragDrop;
  72.     property OnDragOver;
  73.     property OnEndDrag;
  74.     property OnEnter;
  75.     property OnExit;
  76.     property OnStartDrag;
  77.     property OnUpClick: TNotifyEvent read FOnUpClick write FOnUpClick;
  78.   end;
  79.  
  80. { TSpinEdit }
  81.  
  82.   TSpinEdit = class(TCustomEdit)
  83.   private
  84.     FMinValue: LongInt;
  85.     FMaxValue: LongInt;
  86.     FIncrement: LongInt;
  87.     FButton: TSpinButton;
  88.     FEditorEnabled: Boolean;
  89.     function GetMinHeight: Integer;
  90.     function GetValue: LongInt;
  91.     function CheckValue (NewValue: LongInt): LongInt;
  92.     procedure SetValue (NewValue: LongInt);
  93.     procedure SetEditRect;
  94.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  95.     procedure CMEnter(var Message: TCMGotFocus); message CM_ENTER;
  96.     procedure CMExit(var Message: TCMExit);   message CM_EXIT;
  97.     procedure WMPaste(var Message: TWMPaste);   message WM_PASTE;
  98.     procedure WMCut(var Message: TWMCut);   message WM_CUT;
  99.   protected
  100.     procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  101.     function IsValidChar(Key: Char): Boolean; virtual;
  102.     procedure UpClick (Sender: TObject); virtual;
  103.     procedure DownClick (Sender: TObject); virtual;
  104.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  105.     procedure KeyPress(var Key: Char); override;
  106.     procedure CreateParams(var Params: TCreateParams); override;
  107.     procedure CreateWnd; override;
  108.   public
  109.     constructor Create(AOwner: TComponent); override;
  110.     destructor Destroy; override;
  111.     property Button: TSpinButton read FButton;
  112.   published
  113.     property AutoSelect;
  114.     property AutoSize;
  115.     property Color;
  116.     property Ctl3D;
  117.     property DragCursor;
  118.     property DragMode;
  119.     property EditorEnabled: Boolean read FEditorEnabled write FEditorEnabled default True;
  120.     property Enabled;
  121.     property Font;
  122.     property Increment: LongInt read FIncrement write FIncrement default 1;
  123.     property MaxLength;
  124.     property MaxValue: LongInt read FMaxValue write FMaxValue;
  125.     property MinValue: LongInt read FMinValue write FMinValue;
  126.     property ParentColor;
  127.     property ParentCtl3D;
  128.     property ParentFont;
  129.     property ParentShowHint;
  130.     property PopupMenu;
  131.     property ReadOnly;
  132.     property ShowHint;
  133.     property TabOrder;
  134.     property TabStop;
  135.     property Value: LongInt read GetValue write SetValue;
  136.     property Visible;
  137.     property OnChange;
  138.     property OnClick;
  139.     property OnDblClick;
  140.     property OnDragDrop;
  141.     property OnDragOver;
  142.     property OnEndDrag;
  143.     property OnEnter;
  144.     property OnExit;
  145.     property OnKeyDown;
  146.     property OnKeyPress;
  147.     property OnKeyUp;
  148.     property OnMouseDown;
  149.     property OnMouseMove;
  150.     property OnMouseUp;
  151.     property OnStartDrag;
  152.   end;
  153.  
  154. { TTimerSpeedButton }
  155.  
  156.   TTimeBtnState = set of (tbFocusRect, tbAllowTimer);
  157.  
  158.   TTimerSpeedButton = class(TSpeedButton)
  159.   private
  160.     FRepeatTimer: TTimer;
  161.     FTimeBtnState: TTimeBtnState;
  162.     procedure TimerExpired(Sender: TObject);
  163.   protected
  164.     procedure Paint; override;
  165.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  166.       X, Y: Integer); override;
  167.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  168.       X, Y: Integer); override;
  169.   public
  170.     destructor Destroy; override;
  171.     property TimeBtnState: TTimeBtnState read FTimeBtnState write FTimeBtnState;
  172.   end;
  173.  
  174. implementation
  175.  
  176. {$R SPIN}
  177.  
  178. { TSpinButton }
  179.  
  180. constructor TSpinButton.Create(AOwner: TComponent);
  181. begin
  182.   inherited Create(AOwner);
  183.   ControlStyle := ControlStyle - [csAcceptsControls, csSetCaption] +
  184.     [csFramed, csOpaque];
  185.  
  186.   FUpButton := CreateButton;
  187.   FDownButton := CreateButton;
  188.   UpGlyph := nil;
  189.   DownGlyph := nil;
  190.  
  191.   Width := 20;
  192.   Height := 25;
  193.   FFocusedButton := FUpButton;
  194. end;
  195.  
  196. function TSpinButton.CreateButton: TTimerSpeedButton;
  197. begin
  198.   Result := TTimerSpeedButton.Create (Self);
  199.   Result.OnClick := BtnClick;
  200.   Result.OnMouseDown := BtnMouseDown;
  201.   Result.Visible := True;
  202.   Result.Enabled := True;
  203.   Result.TimeBtnState := [tbAllowTimer];
  204.   Result.Parent := Self;
  205. end;
  206.  
  207. procedure TSpinButton.Notification(AComponent: TComponent;
  208.   Operation: TOperation);
  209. begin
  210.   inherited Notification(AComponent, Operation);
  211.   if (Operation = opRemove) and (AComponent = FFocusControl) then
  212.     FFocusControl := nil;
  213. end;
  214.  
  215. procedure TSpinButton.AdjustSize (var W: Integer; var H: Integer);
  216. begin
  217.   if (FUpButton = nil) or (csLoading in ComponentState) then Exit;
  218.   if W < 15 then W := 15;
  219.   FUpButton.SetBounds (0, 0, W, H div 2);
  220.   FDownButton.SetBounds (0, FUpButton.Height - 1, W, H - FUpButton.Height + 1);
  221. end;
  222.  
  223. procedure TSpinButton.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  224. var
  225.   W, H: Integer;
  226. begin
  227.   W := AWidth;
  228.   H := AHeight;
  229.   AdjustSize (W, H);
  230.   inherited SetBounds (ALeft, ATop, W, H);
  231. end;
  232.  
  233. procedure TSpinButton.WMSize(var Message: TWMSize);
  234. var
  235.   W, H: Integer;
  236. begin
  237.   inherited;
  238.  
  239.   { check for minimum size }
  240.   W := Width;
  241.   H := Height;
  242.   AdjustSize (W, H);
  243.   if (W <> Width) or (H <> Height) then
  244.     inherited SetBounds(Left, Top, W, H);
  245.   Message.Result := 0;
  246. end;
  247.  
  248. procedure TSpinButton.WMSetFocus(var Message: TWMSetFocus);
  249. begin
  250.   FFocusedButton.TimeBtnState := FFocusedButton.TimeBtnState + [tbFocusRect];
  251.   FFocusedButton.Invalidate;
  252. end;
  253.  
  254. procedure TSpinButton.WMKillFocus(var Message: TWMKillFocus);
  255. begin
  256.   FFocusedButton.TimeBtnState := FFocusedButton.TimeBtnState - [tbFocusRect];
  257.   FFocusedButton.Invalidate;
  258. end;
  259.  
  260. procedure TSpinButton.KeyDown(var Key: Word; Shift: TShiftState);
  261. begin
  262.   case Key of
  263.     VK_UP:
  264.       begin
  265.         SetFocusBtn (FUpButton);
  266.         FUpButton.Click;
  267.       end;
  268.     VK_DOWN:
  269.       begin
  270.         SetFocusBtn (FDownButton);
  271.         FDownButton.Click;
  272.       end;
  273.     VK_SPACE:
  274.       FFocusedButton.Click;
  275.   end;
  276. end;
  277.  
  278. procedure TSpinButton.BtnMouseDown (Sender: TObject; Button: TMouseButton;
  279.   Shift: TShiftState; X, Y: Integer);
  280. begin
  281.   if Button = mbLeft then
  282.   begin
  283.     SetFocusBtn (TTimerSpeedButton (Sender));
  284.     if (FFocusControl <> nil) and FFocusControl.TabStop and 
  285.         FFocusControl.CanFocus and (GetFocus <> FFocusControl.Handle) then
  286.       FFocusControl.SetFocus
  287.     else if TabStop and (GetFocus <> Handle) and CanFocus then
  288.       SetFocus;
  289.   end;
  290. end;
  291.  
  292. procedure TSpinButton.BtnClick(Sender: TObject);
  293. begin
  294.   if Sender = FUpButton then
  295.   begin
  296.     if Assigned(FOnUpClick) then FOnUpClick(Self);
  297.   end
  298.   else
  299.     if Assigned(FOnDownClick) then FOnDownClick(Self);
  300. end;
  301.  
  302. procedure TSpinButton.SetFocusBtn (Btn: TTimerSpeedButton);
  303. begin
  304.   if TabStop and CanFocus and  (Btn <> FFocusedButton) then
  305.   begin
  306.     FFocusedButton.TimeBtnState := FFocusedButton.TimeBtnState - [tbFocusRect];
  307.     FFocusedButton := Btn;
  308.     if (GetFocus = Handle) then 
  309.     begin
  310.        FFocusedButton.TimeBtnState := FFocusedButton.TimeBtnState + [tbFocusRect];
  311.        Invalidate;
  312.     end;
  313.   end;
  314. end;
  315.  
  316. procedure TSpinButton.WMGetDlgCode(var Message: TWMGetDlgCode);
  317. begin
  318.   Message.Result := DLGC_WANTARROWS;
  319. end;
  320.  
  321. procedure TSpinButton.Loaded;
  322. var
  323.   W, H: Integer;
  324. begin
  325.   inherited Loaded;
  326.   W := Width;
  327.   H := Height;
  328.   AdjustSize (W, H);
  329.   if (W <> Width) or (H <> Height) then
  330.     inherited SetBounds (Left, Top, W, H);
  331. end;
  332.  
  333. function TSpinButton.GetUpGlyph: TBitmap;
  334. begin
  335.   Result := FUpButton.Glyph;
  336. end;
  337.  
  338. procedure TSpinButton.SetUpGlyph(Value: TBitmap);
  339. begin
  340.   if Value <> nil then
  341.     FUpButton.Glyph := Value
  342.   else
  343.   begin
  344.     FUpButton.Glyph.Handle := LoadBitmap(HInstance, 'SpinUp');
  345.     FUpButton.NumGlyphs := 1;
  346.     FUpButton.Invalidate;
  347.   end;
  348. end;
  349.  
  350. function TSpinButton.GetUpNumGlyphs: TNumGlyphs;
  351. begin
  352.   Result := FUpButton.NumGlyphs;
  353. end;
  354.  
  355. procedure TSpinButton.SetUpNumGlyphs(Value: TNumGlyphs);
  356. begin
  357.   FUpButton.NumGlyphs := Value;
  358. end;
  359.  
  360. function TSpinButton.GetDownGlyph: TBitmap;
  361. begin
  362.   Result := FDownButton.Glyph;
  363. end;
  364.  
  365. procedure TSpinButton.SetDownGlyph(Value: TBitmap);
  366. begin
  367.   if Value <> nil then
  368.     FDownButton.Glyph := Value
  369.   else
  370.   begin
  371.     FDownButton.Glyph.Handle := LoadBitmap(HInstance, 'SpinDown');
  372.     FUpButton.NumGlyphs := 1;
  373.     FDownButton.Invalidate;
  374.   end;
  375. end;
  376.  
  377. function TSpinButton.GetDownNumGlyphs: TNumGlyphs;
  378. begin
  379.   Result := FDownButton.NumGlyphs;
  380. end;
  381.  
  382. procedure TSpinButton.SetDownNumGlyphs(Value: TNumGlyphs);
  383. begin
  384.   FDownButton.NumGlyphs := Value;
  385. end;
  386.  
  387. { TSpinEdit }
  388.  
  389. constructor TSpinEdit.Create(AOwner: TComponent);
  390. begin
  391.   inherited Create(AOwner);
  392.   FButton := TSpinButton.Create (Self);
  393.   FButton.Width := 15;
  394.   FButton.Height := 17;
  395.   FButton.Visible := True;  
  396.   FButton.Parent := Self;
  397.   FButton.FocusControl := Self;
  398.   FButton.OnUpClick := UpClick;
  399.   FButton.OnDownClick := DownClick;
  400.   Text := '0';
  401.   ControlStyle := ControlStyle - [csSetCaption];
  402.   FIncrement := 1;
  403.   FEditorEnabled := True;
  404. end;
  405.  
  406. destructor TSpinEdit.Destroy;
  407. begin
  408.   FButton := nil;
  409.   inherited Destroy;
  410. end;
  411.  
  412. procedure TSpinEdit.GetChildren(Proc: TGetChildProc; Root: TComponent);
  413. begin
  414. end;
  415.  
  416. procedure TSpinEdit.KeyDown(var Key: Word; Shift: TShiftState);
  417. begin
  418.   if Key = VK_UP then UpClick (Self)
  419.   else if Key = VK_DOWN then DownClick (Self);
  420.   inherited KeyDown(Key, Shift);
  421. end;
  422.  
  423. procedure TSpinEdit.KeyPress(var Key: Char);
  424. begin
  425.   if not IsValidChar(Key) then
  426.   begin
  427.     Key := #0;
  428.     MessageBeep(0)
  429.   end;
  430.   if Key <> #0 then inherited KeyPress(Key);
  431. end;
  432.  
  433. function TSpinEdit.IsValidChar(Key: Char): Boolean;
  434. begin
  435.   Result := (Key in [DecimalSeparator, '+', '-', '0'..'9']) or
  436.     ((Key < #32) and (Key <> Chr(VK_RETURN)));
  437.   if not FEditorEnabled and Result and ((Key >= #32) or
  438.       (Key = Char(VK_BACK)) or (Key = Char(VK_DELETE))) then
  439.     Result := False;
  440. end;
  441.  
  442. procedure TSpinEdit.CreateParams(var Params: TCreateParams);
  443. begin
  444.   inherited CreateParams(Params);
  445. {  Params.Style := Params.Style and not WS_BORDER;  }
  446.   Params.Style := Params.Style or ES_MULTILINE or WS_CLIPCHILDREN;
  447. end;
  448.  
  449. procedure TSpinEdit.CreateWnd;
  450. begin
  451.   inherited CreateWnd;
  452.   SetEditRect;
  453. end;
  454.  
  455. procedure TSpinEdit.SetEditRect;
  456. var
  457.   Loc: TRect;
  458. begin
  459.   SendMessage(Handle, EM_GETRECT, 0, LongInt(@Loc));
  460.   Loc.Bottom := ClientHeight + 1;  {+1 is workaround for windows paint bug}
  461.   Loc.Right := ClientWidth - FButton.Width - 2;
  462.   Loc.Top := 0;  
  463.   Loc.Left := 0;  
  464.   SendMessage(Handle, EM_SETRECTNP, 0, LongInt(@Loc));
  465.   SendMessage(Handle, EM_GETRECT, 0, LongInt(@Loc));  {debug}
  466. end;
  467.  
  468. procedure TSpinEdit.WMSize(var Message: TWMSize);
  469. var
  470.   MinHeight: Integer;
  471. begin
  472.   inherited;
  473.   MinHeight := GetMinHeight;
  474.     { text edit bug: if size to less than minheight, then edit ctrl does
  475.       not display the text }
  476.   if Height < MinHeight then   
  477.     Height := MinHeight
  478.   else if FButton <> nil then
  479.   begin
  480.     if NewStyleControls and Ctl3D then
  481.       FButton.SetBounds(Width - FButton.Width - 5, 0, FButton.Width, Height - 5)
  482.     else FButton.SetBounds (Width - FButton.Width, 1, FButton.Width, Height - 3);
  483.     SetEditRect;
  484.   end;
  485. end;
  486.  
  487. function TSpinEdit.GetMinHeight: Integer;
  488. var
  489.   DC: HDC;
  490.   SaveFont: HFont;
  491.   I: Integer;
  492.   SysMetrics, Metrics: TTextMetric;
  493. begin
  494.   DC := GetDC(0);
  495.   GetTextMetrics(DC, SysMetrics);
  496.   SaveFont := SelectObject(DC, Font.Handle);
  497.   GetTextMetrics(DC, Metrics);
  498.   SelectObject(DC, SaveFont);
  499.   ReleaseDC(0, DC);
  500.   I := SysMetrics.tmHeight;
  501.   if I > Metrics.tmHeight then I := Metrics.tmHeight;
  502.   Result := Metrics.tmHeight + I div 4 + GetSystemMetrics(SM_CYBORDER) * 4 + 2;
  503. end;
  504.  
  505. procedure TSpinEdit.UpClick (Sender: TObject);
  506. begin
  507.   if ReadOnly then MessageBeep(0)
  508.   else Value := Value + FIncrement;
  509. end;
  510.  
  511. procedure TSpinEdit.DownClick (Sender: TObject);
  512. begin
  513.   if ReadOnly then MessageBeep(0)
  514.   else Value := Value - FIncrement;
  515. end;
  516.  
  517. procedure TSpinEdit.WMPaste(var Message: TWMPaste);   
  518. begin
  519.   if not FEditorEnabled or ReadOnly then Exit;
  520.   inherited;
  521. end;
  522.  
  523. procedure TSpinEdit.WMCut(var Message: TWMPaste);   
  524. begin
  525.   if not FEditorEnabled or ReadOnly then Exit;
  526.   inherited;
  527. end;
  528.  
  529. procedure TSpinEdit.CMExit(var Message: TCMExit);
  530. begin
  531.   inherited;
  532.   if CheckValue (Value) <> Value then
  533.     SetValue (Value);
  534. end;
  535.  
  536. function TSpinEdit.GetValue: LongInt;
  537. begin
  538.   try
  539.     Result := StrToInt (Text);
  540.   except
  541.     Result := FMinValue;
  542.   end;
  543. end;
  544.  
  545. procedure TSpinEdit.SetValue (NewValue: LongInt);
  546. begin
  547.   Text := IntToStr (CheckValue (NewValue));
  548. end;
  549.  
  550. function TSpinEdit.CheckValue (NewValue: LongInt): LongInt;
  551. begin
  552.   Result := NewValue;
  553.   if (FMaxValue <> FMinValue) then
  554.   begin
  555.     if NewValue < FMinValue then
  556.       Result := FMinValue
  557.     else if NewValue > FMaxValue then
  558.       Result := FMaxValue;
  559.   end;
  560. end;
  561.  
  562. procedure TSpinEdit.CMEnter(var Message: TCMGotFocus);
  563. begin
  564.   if AutoSelect and not (csLButtonDown in ControlState) then
  565.     SelectAll;
  566.   inherited;
  567. end;
  568.  
  569. {TTimerSpeedButton}
  570.  
  571. destructor TTimerSpeedButton.Destroy;
  572. begin
  573.   if FRepeatTimer <> nil then
  574.     FRepeatTimer.Free;
  575.   inherited Destroy;
  576. end;
  577.  
  578. procedure TTimerSpeedButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
  579.   X, Y: Integer);
  580. begin
  581.   inherited MouseDown (Button, Shift, X, Y);
  582.   if tbAllowTimer in FTimeBtnState then
  583.   begin
  584.     if FRepeatTimer = nil then
  585.       FRepeatTimer := TTimer.Create(Self);
  586.  
  587.     FRepeatTimer.OnTimer := TimerExpired;
  588.     FRepeatTimer.Interval := InitRepeatPause;
  589.     FRepeatTimer.Enabled  := True;
  590.   end;
  591. end;
  592.  
  593. procedure TTimerSpeedButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
  594.                                   X, Y: Integer);
  595. begin
  596.   inherited MouseUp (Button, Shift, X, Y);
  597.   if FRepeatTimer <> nil then
  598.     FRepeatTimer.Enabled  := False;
  599. end;
  600.  
  601. procedure TTimerSpeedButton.TimerExpired(Sender: TObject);
  602. begin
  603.   FRepeatTimer.Interval := RepeatPause;
  604.   if (FState = bsDown) and MouseCapture then
  605.   begin
  606.     try
  607.       Click;
  608.     except
  609.       FRepeatTimer.Enabled := False;
  610.       raise;
  611.     end;
  612.   end;
  613. end;
  614.  
  615. procedure TTimerSpeedButton.Paint;
  616. var
  617.   R: TRect;
  618. begin
  619.   inherited Paint;
  620.   if tbFocusRect in FTimeBtnState then
  621.   begin
  622.     R := Bounds(0, 0, Width, Height);
  623.     InflateRect(R, -3, -3);
  624.     if FState = bsDown then
  625.       OffsetRect(R, 1, 1);
  626.     DrawFocusRect(Canvas.Handle, R);
  627.   end;
  628. end;
  629.  
  630. end.
  631.